1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the
10   * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11   * express or implied. See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  
15  package com.google.common.primitives;
16  
17  import static com.google.common.base.Preconditions.checkArgument;
18  import static com.google.common.base.Preconditions.checkNotNull;
19  
20  import com.google.common.annotations.GwtCompatible;
21  
22  import java.io.Serializable;
23  import java.math.BigInteger;
24  
25  import javax.annotation.CheckReturnValue;
26  import javax.annotation.Nullable;
27  
28  /**
29   * A wrapper class for unsigned {@code long} values, supporting arithmetic operations.
30   *
31   * <p>In some cases, when speed is more important than code readability, it may be faster simply to
32   * treat primitive {@code long} values as unsigned, using the methods from {@link UnsignedLongs}.
33   *
34   * <p>See the Guava User Guide article on <a href=
35   * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
36   * unsigned primitive utilities</a>.
37   *
38   * @author Louis Wasserman
39   * @author Colin Evans
40   * @since 11.0
41   */
42  @GwtCompatible(serializable = true)
43  public final class UnsignedLong extends Number implements Comparable<UnsignedLong>, Serializable {
44  
45    private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
46  
47    public static final UnsignedLong ZERO = new UnsignedLong(0);
48    public static final UnsignedLong ONE = new UnsignedLong(1);
49    public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L);
50  
51    private final long value;
52  
53    private UnsignedLong(long value) {
54      this.value = value;
55    }
56  
57    /**
58     * Returns an {@code UnsignedLong} corresponding to a given bit representation.
59     * The argument is interpreted as an unsigned 64-bit value. Specifically, the sign bit
60     * of {@code bits} is interpreted as a normal bit, and all other bits are treated as usual.
61     *
62     * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
63     * otherwise, the result will be equal to {@code 2^64 + bits}.
64     *
65     * <p>To represent decimal constants less than {@code 2^63}, consider {@link #valueOf(long)}
66     * instead.
67     *
68     * @since 14.0
69     */
70    public static UnsignedLong fromLongBits(long bits) {
71      // TODO(user): consider caching small values, like Long.valueOf
72      return new UnsignedLong(bits);
73    }
74  
75    /**
76     * Returns an {@code UnsignedLong} representing the same value as the specified {@code long}.
77     *
78     * @throws IllegalArgumentException if {@code value} is negative
79     * @since 14.0
80     */
81    public static UnsignedLong valueOf(long value) {
82      checkArgument(value >= 0,
83          "value (%s) is outside the range for an unsigned long value", value);
84      return fromLongBits(value);
85    }
86  
87    /**
88     * Returns a {@code UnsignedLong} representing the same value as the specified
89     * {@code BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
90     *
91     * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^64}
92     */
93    public static UnsignedLong valueOf(BigInteger value) {
94      checkNotNull(value);
95      checkArgument(value.signum() >= 0 && value.bitLength() <= Long.SIZE,
96          "value (%s) is outside the range for an unsigned long value", value);
97      return fromLongBits(value.longValue());
98    }
99  
100   /**
101    * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
102    * an unsigned {@code long} value.
103    *
104    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
105    *         value
106    */
107   public static UnsignedLong valueOf(String string) {
108     return valueOf(string, 10);
109   }
110 
111   /**
112    * Returns an {@code UnsignedLong} holding the value of the specified {@code String}, parsed as
113    * an unsigned {@code long} value in the specified radix.
114    *
115    * @throws NumberFormatException if the string does not contain a parsable unsigned {@code long}
116    *         value, or {@code radix} is not between {@link Character#MIN_RADIX} and
117    *         {@link Character#MAX_RADIX}
118    */
119   public static UnsignedLong valueOf(String string, int radix) {
120     return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix));
121   }
122 
123   /**
124    * Returns the result of adding this and {@code val}. If the result would have more than 64 bits,
125    * returns the low 64 bits of the result.
126    *
127    * @since 14.0
128    */
129   public UnsignedLong plus(UnsignedLong val) {
130     return fromLongBits(this.value + checkNotNull(val).value);
131   }
132 
133   /**
134    * Returns the result of subtracting this and {@code val}. If the result would have more than 64
135    * bits, returns the low 64 bits of the result.
136    *
137    * @since 14.0
138    */
139   public UnsignedLong minus(UnsignedLong val) {
140     return fromLongBits(this.value - checkNotNull(val).value);
141   }
142 
143   /**
144    * Returns the result of multiplying this and {@code val}. If the result would have more than 64
145    * bits, returns the low 64 bits of the result.
146    *
147    * @since 14.0
148    */
149   @CheckReturnValue
150   public UnsignedLong times(UnsignedLong val) {
151     return fromLongBits(value * checkNotNull(val).value);
152   }
153 
154   /**
155    * Returns the result of dividing this by {@code val}.
156    *
157    * @since 14.0
158    */
159   @CheckReturnValue
160   public UnsignedLong dividedBy(UnsignedLong val) {
161     return fromLongBits(UnsignedLongs.divide(value, checkNotNull(val).value));
162   }
163 
164   /**
165    * Returns this modulo {@code val}.
166    *
167    * @since 14.0
168    */
169   @CheckReturnValue
170   public UnsignedLong mod(UnsignedLong val) {
171     return fromLongBits(UnsignedLongs.remainder(value, checkNotNull(val).value));
172   }
173 
174   /**
175    * Returns the value of this {@code UnsignedLong} as an {@code int}.
176    */
177   @Override
178   public int intValue() {
179     return (int) value;
180   }
181 
182   /**
183    * Returns the value of this {@code UnsignedLong} as a {@code long}. This is an inverse operation
184    * to {@link #fromLongBits}.
185    *
186    * <p>Note that if this {@code UnsignedLong} holds a value {@code >= 2^63}, the returned value
187    * will be equal to {@code this - 2^64}.
188    */
189   @Override
190   public long longValue() {
191     return value;
192   }
193 
194   /**
195    * Returns the value of this {@code UnsignedLong} as a {@code float}, analogous to a widening
196    * primitive conversion from {@code long} to {@code float}, and correctly rounded.
197    */
198   @Override
199   public float floatValue() {
200     @SuppressWarnings("cast")
201     float fValue = (float) (value & UNSIGNED_MASK);
202     if (value < 0) {
203       fValue += 0x1.0p63f;
204     }
205     return fValue;
206   }
207 
208   /**
209    * Returns the value of this {@code UnsignedLong} as a {@code double}, analogous to a widening
210    * primitive conversion from {@code long} to {@code double}, and correctly rounded.
211    */
212   @Override
213   public double doubleValue() {
214     @SuppressWarnings("cast")
215     double dValue = (double) (value & UNSIGNED_MASK);
216     if (value < 0) {
217       dValue += 0x1.0p63;
218     }
219     return dValue;
220   }
221 
222   /**
223    * Returns the value of this {@code UnsignedLong} as a {@link BigInteger}.
224    */
225   public BigInteger bigIntegerValue() {
226     BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
227     if (value < 0) {
228       bigInt = bigInt.setBit(Long.SIZE - 1);
229     }
230     return bigInt;
231   }
232 
233   @Override
234   public int compareTo(UnsignedLong o) {
235     checkNotNull(o);
236     return UnsignedLongs.compare(value, o.value);
237   }
238 
239   @Override
240   public int hashCode() {
241     return Longs.hashCode(value);
242   }
243 
244   @Override
245   public boolean equals(@Nullable Object obj) {
246     if (obj instanceof UnsignedLong) {
247       UnsignedLong other = (UnsignedLong) obj;
248       return value == other.value;
249     }
250     return false;
251   }
252 
253   /**
254    * Returns a string representation of the {@code UnsignedLong} value, in base 10.
255    */
256   @Override
257   public String toString() {
258     return UnsignedLongs.toString(value);
259   }
260 
261   /**
262    * Returns a string representation of the {@code UnsignedLong} value, in base {@code radix}. If
263    * {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
264    * {@code 10} is used.
265    */
266   public String toString(int radix) {
267     return UnsignedLongs.toString(value, radix);
268   }
269 }